/*
This file is part of MMM.

MMM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

MMM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with MMM.  If not, see <http://www.gnu.org/licenses/>.
*
* @package    MMM
* @author     Andre Meixner
* @copyright  2017 High Performance Humanoid Technologies (H2T), Karlsruhe, Germany
*
*/

#ifndef __MMM_SEGMENTATIONPOINTSWIDGET_H_
#define __MMM_SEGMENTATIONPOINTSWIDGET_H_

#include <QPainter>
#include <QWidget>
#include <QMouseEvent>
#include <QGridLayout>

#ifndef Q_MOC_RUN
#include "../MotionSegmenter.h"
#endif

class SegmentationPointWidget : public QWidget
{
    Q_OBJECT

public:
    SegmentationPointWidget(QWidget* parent, float xValue, float minTimestep, float maxTimestep, float currentTimestep = -1.0f) :
        QWidget(parent),
        xValue(xValue),
        minTimestep(minTimestep),
        maxTimestep(maxTimestep),
        currentTimestep(currentTimestep)
    {
    }

    void repaint(float minTimestep, float maxTimestep, float currentTimestep = -1.0) {
        this->minTimestep = minTimestep;
        this->maxTimestep = maxTimestep;
        this->currentTimestep = currentTimestep;
        this->update();
    }

    void repaint(float currentTimestep) {
        this->currentTimestep = currentTimestep;
        this->update();
    }


    QSize minimumSizeHint() const {
        return QSize(1, 7);
    }

protected:
    void paintEvent(QPaintEvent *) {
        qreal yPosition = ((qreal)this->height()) / 2.0;

        QPainter painter(this);
        painter.setRenderHint(QPainter::Antialiasing, true);

        qreal factor = ((qreal)(this->width() - 6) / (qreal)(maxTimestep - minTimestep));

        float size = 6.0;
        if (currentTimestep >= minTimestep && currentTimestep <= maxTimestep) {
            painter.setOpacity(1.0);
            qreal x = xValue + currentTimestep * factor;
            QRectF rect(x - 1.0, yPosition - size, 2.0, 2.0 * size);
            painter.fillRect(rect, Qt::green);
        }
    }

private:

    float xValue;
    float minTimestep;
    float maxTimestep;
    float currentTimestep;
};

class SegmentationPointsWidget : public QWidget
{
    Q_OBJECT

public:

    SegmentationPointsWidget(std::vector<MMM::SegmentationPtr> &segmentationResult, float minTimestep, float maxTimestep, QWidget *parent = 0) :
        QWidget(parent),
        segmentationResult(segmentationResult),
        minTimestep(minTimestep),
        maxTimestep(maxTimestep),
        xValue(3.0),
        spWidget(new SegmentationPointWidget(this, xValue, minTimestep, maxTimestep))
    {
        QGridLayout* layout = new QGridLayout(this);
        layout->setMargin(0);
        layout->addWidget(spWidget);
        connect(this, SIGNAL(segmentPointClicked(float)), this, SLOT(jumpTo(float)));
    }

    void repaint(std::vector<MMM::SegmentationPtr> segmentationResult, float minTimestep, float maxTimestep) {
        this->segmentationResult = segmentationResult;
        this->minTimestep = minTimestep;
        this->maxTimestep = maxTimestep;
        spWidget->repaint(minTimestep, maxTimestep);
        this->update();
    }

    QSize minimumSizeHint() const {
        return QSize(1, 7);
    }

protected:
    void paintEvent(QPaintEvent *) {
        qreal yPosition = ((qreal)this->height()) / 2.0;

        QPainter painter(this);
        painter.setRenderHint(QPainter::Antialiasing, true);
        QRectF line(xValue, yPosition, this->width() - 5, 1.0);
        painter.drawRect(line);

        qreal factor = ((qreal)(this->width() - 6) / (qreal)(maxTimestep - minTimestep));

        // draw all segmentations
        painter.setOpacity(1.0);
        float s_size = 4.0;
        for (auto segmentation : segmentationResult) {
            qreal x = xValue + segmentation->getMinTimestep() * factor;
            qreal width = (segmentation->getMaxTimestep() - segmentation->getMinTimestep()) * factor;
            QRectF rect(x, yPosition - s_size, width, 2.0 * s_size);
            painter.fillRect(rect, Qt::red);
        }

        // draw key frames
        float k_size = 6.0;
        painter.setOpacity(1.0);
        for (auto segmentation : segmentationResult) {
            qreal x = xValue + segmentation->getKeyTimestep() * factor;
            QRectF rect(x - 1.0, yPosition - k_size, 2.0, 2.0 * k_size);
            painter.fillRect(rect, Qt::blue);
        }
    }

    void mousePressEvent(QMouseEvent* event) {
        qreal factor = ((qreal)(this->width() - 6) / (qreal)(maxTimestep - minTimestep));
        //qreal x_min_last;
        qreal x_max_last;
        for (unsigned int i = 0; i < segmentationResult.size(); i++) {
            qreal x_min = xValue + segmentationResult[i]->getMinTimestep() * factor;
            qreal x_max = xValue + segmentationResult[i]->getMaxTimestep() * factor;
            if ((i == 0 && event->x() <= x_max) || i == segmentationResult.size() - 1) {
                emit segmentPointClicked(segmentationResult[i]->getKeyTimestep());
                emit segmentPointClickedIndex(i);
                break;
            }
            else if (i != 0 && event->x() < x_min && event->x() - x_max_last < x_min - event->x()) {
                emit segmentPointClicked(segmentationResult[i - 1]->getKeyTimestep());
                emit segmentPointClickedIndex(i - 1);
                break;
            }
            else if (i != 0 && event->x() < x_min && event->x() - x_max_last > x_min - event->x()) {
                emit segmentPointClicked(segmentationResult[i]->getKeyTimestep());
                emit segmentPointClickedIndex(i);
                break;
            }
            else {
                //x_min_last = x_min;
                x_max_last = x_max;
            }
        }
    }

private:
    std::vector<MMM::SegmentationPtr> segmentationResult;
    float minTimestep;
    float maxTimestep;
    qreal xValue;
    SegmentationPointWidget* spWidget;

public slots:
    void jumpTo(float currentTimestep) {
        spWidget->repaint(currentTimestep);
    }

signals:
    void segmentPointClicked(float timestep);
    void segmentPointClickedIndex(int index);

};





#endif // __MMM_SEGMENTATIONPOINTSWIDGET_H_
